/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.common;

import java.util.HashMap;
import java.util.Map;

/**
 * 上下文变量
 * <p>所有需要在本地线程存储的数据都存放在这，key-value形式
 * <p>默认实现了"数据集"的概念{@link DataSource}
 */
public class ContextHolder {
	private static final ThreadLocal<Map<String, Object>> contextHolder
			= new ThreadLocal<>();

	public static void setDataSource(DataSourceContextKey dataSource) {
		Map<String, Object> holder = getContextHolder();
		holder.put(DataSourceContextKey.class.getName(), dataSource);
	}

	/**
	 * 快捷方法，返回当前数据集的字符串形式
	 */
	public static String getDataSource() {
		Map<String, Object> holder = getContextHolder();
		Object dataSource = holder.get(DataSourceContextKey.class.getName());
		return dataSource==null?DataSource.YHAO_CLOUD.toString():dataSource.toString();
	}

	/**
	 * 返回当前数据集
	 * @return
	 */
	public static DataSourceContextKey getDataSourceKey() {
		Map<String, Object> holder = getContextHolder();
		DataSourceContextKey dataSource = (DataSourceContextKey)holder.get(DataSourceContextKey.class.getName());
		return dataSource==null?DataSource.YHAO_CLOUD :dataSource;
	}

	/**
	 * 设置上下文数据
	 * @param type 上下文参数类型
	 * @param data 数据
	 */
	public static void setContextData(Class<? extends ContextKey> type,Object data) {
		Map<String, Object> holder = getContextHolder();
		holder.put(type.getName(), data);
	}

	/**
	 * 获取上下文数据
	 * @param type 上下文参数类型
	 * @return
	 */
	public static Object getContextData(Class<? extends ContextKey> type) {
		Map<String, Object> holder = getContextHolder();
		return holder.get(type.getName());
	}

	/**
	 * 移除上下文数据
	 * @param type 上下文参数类型
	 * @return
	 */
	public static Object removeContextData(Class<? extends ContextKey> type) {
		Map<String, Object> holder = getContextHolder();
		return holder.remove(type.getName());
	}

	/**
	 * 操作用风险，请勿直接调用
	 */
	public static Map<String, Object> getContextHolder(){
		Map<String, Object> holder = contextHolder.get();
		if(holder == null) {
			holder = new HashMap<>();
			contextHolder.set(holder);
		}
		return holder;
	}

	/**
	 * 操作用风险，请勿直接调用
	 * @param holder
	 */
	public static void setContextHolder(Map<String, Object> holder){
		contextHolder.set(holder);
	}

	/**
	 * context键名接口
	 *
	 * <p>上下文数据定义接口</p>
	 */
	public interface ContextKey{}

	/**
	 * 数据集切换接口
	 *
	 * @see ContextKey
	 */
	public interface DataSourceContextKey extends ContextKey{}

	/**
	 * 默认数据集上下文
	 *
	 * @see DataSourceContextKey
	 */
	enum DataSource implements DataSourceContextKey {
		YHAO_CLOUD
	}
}
